package com.pvdnc.xdynamic.loader.module;

import android.content.Context;
import android.util.Log;

import com.pvdnc.xdynamic.common.ModuleCallResult;
import com.pvdnc.xdynamic.common.ModuleStartArgs;
import com.pvdnc.xdynamic.common.XModule;

import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;

public class XModuleManager {
    private static final String TAG=XModuleManager.class.getSimpleName();

    private static final AtomicReference<XModuleManager> sInstance=new AtomicReference<>();

    public static void systemReady(Context context){
        sInstance.set(new XModuleManager(context));
    }

    public static XModuleManager get(){
        return sInstance.get();
    }

    private final Map<String,ModuleRecord> mModuleMap=new ConcurrentHashMap<>();

    private Context mContext;

    private XModuleManager(Context context){
        mContext=context;
    }

    public void loadModules() {
        File rootDir = ModuleDir.getModuleRootDir(mContext);
        File[] moduleDirs= rootDir.listFiles();
        if(moduleDirs==null){
            Log.e(TAG,"no module can be loaded from root dir:"+rootDir);
            return;
        }
        for (File moduleDir:moduleDirs){
            if(!moduleDir.isDirectory()){
                Log.d(TAG,"skip file:"+moduleDir);
                continue;
            }
            //加载模块
            File apkFile=ModuleDir.getModuleApkFile(moduleDir);
            try {
                 ModuleRecord record= loadModule(apkFile);
                 Log.d(TAG,"loaded module:"+record.getModuleName());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public ModuleRecord loadModule(File moduleApkFile) throws Exception {
        ModuleLoader loader=new ModuleLoader(mContext,moduleApkFile);
        String moduleName=loader.getModuleName();
        Class<? extends XModule>  entryClass= loader.loadEntryClass();
        ModuleRecord record=new ModuleRecord(loader,entryClass);
        Log.d(TAG,"putting module:"+moduleName);
        mModuleMap.put(moduleName,record);
        return record;
    }

    private ModuleRecord getRecordOrThrow(String moduleName) throws IllegalArgumentException{
        ModuleRecord record= mModuleMap.get(moduleName);
        if(record==null)
            throw new IllegalArgumentException("module:"+moduleName
                    +" does not exist");
        return record;
    }

    public ModuleCallResult callModule(String moduleName, ModuleStartArgs args) throws Exception {
        ModuleRecord record=getRecordOrThrow(moduleName);
        Log.d(TAG,"attempt to call module:"+moduleName);
        return record.callEntry(args);
    }

    public XModule getModule(String moduleName,String instanceName) throws Exception {
        ModuleRecord record=getRecordOrThrow(moduleName);
        return record.getOrCreate(instanceName,false);
    }
}
